package com.cskaoyan.javase.oop3._0abstract._1basic;

/**
 * 抽象类的定义:在继承体系中，从祖先类开始，随着一个个子类的定义，子类变得越来越具体，而祖先类则更具有一般性和抽象性。在这种情况下，为了体现祖先类在设计上的抽象性，我们只将该类作为派生其他类的父类，而不能创建对象实例。这个时候，这样的类，我们称之为抽象类。
 *
 * 通过以上定义,思考什么样的类应该定义为抽象类呢?
 * 只会把继承中祖先类定义成抽象类,为了体现祖先类的抽象性和一般性
 *
 * 抽象类的特点:
 * 语法:
 * [修饰符列表] abstract class 类名{
 *     //类体
 * }
 * 1.类名命名特点
 *      抽象类是一个类,仍然是一个引用数据类型,所以类名应该"大驼峰式"的书写
 *      为了体现抽象类的特殊,命名一般为"Abstract"或者"Base"开头(这算是一种规范)
 *
 * 2.抽象类定义能用哪些修饰符？
 *      思考:能不能用final修饰抽象类
 *      Illegal combination of modifiers: 'final' and 'abstract'
 *      抽象类就是为了继承,final是阻止继承,天生冲突
 *
 * 3.成员特点
 *      普通成员(变量和方法)
 *          都可以定义和普通类是一样的
 *      静态成员
 *          都可以定义和普通类是一样的
 *          当然抽象类有静态成员是比较少见的
 *      抽象方法
 *          思考: 抽象类可不可以没有抽象方法?
 *          语法可以允许没有,但是定义抽象类就是为了抽象方法的,没有抽象方法的抽象类没有意义.
 *          定义语法:
 *          [修饰符列表] abstract 返回值类型 方法名(形参列表);
 *          抽象的子类如果是一个普通类,普通类不允许存在抽象方法,所以普通类继承抽象类,必须实现抽象类中的所有抽象方法.
 *          从这个角度上来说,抽象类中抽象方法其中"占位"的作用,普通子类必须实现全部的抽象方法.
 *          当然抽象类的子类还可以是抽象类,这样就不需要强制实现父类中的抽象方法了.可以选择实现某几个,或者全部都不实现.
 *
 *          思考: abstract修饰方法表示抽象方法,什么样的方法不能用abstract修饰?abstract关键字和哪些关键字不能一起使用?
 *          1.私有方法.不能重写,不能用abstract修饰
 *          2.静态方法,不能重写,不能用abstract修饰
 *          3.构造方法,不能继承,不能用abstract修饰
 *          4.final修饰的方法,不能重写,不能用abstract修饰
 *
 *
 *      构造器
 *          思考: 抽象类不能创建对象,那么有没有构造器?
 *          构造器的作用是在创建对象的过程中,给自身成员变量赋值,要么是创建自身对象赋值,还可以创建子类对象赋值.
 *          所以抽象类是需要构造器的,虽然不能自己赋值,但可以给子类用
 *
 *      代码块
 *          有构造器就有构造代码块
 *          也有静态代码块
 *
 *     以上总结: 抽象类从成员特点和构造器,代码块等上来说,就比普通类多了一个抽象方法,其他的都一样.
 *
 *      思考题:
 *      1.Java当中的一个类,任何情况下,都有构造器!
 *          这是正确的,不管是普通类还是抽象类,不管你有没有在类中写构造器,这个类都有构造器
 *
 *      2.Java当中的一个普通类,可以直接无脑加上abstract关键字吗?(不考虑创建对象)
 *      可以,因为普通类中有的,抽象类都有
 *
 *      3.抽象类可以不可以直接继承一个普通类呢?
 *      是可以的,即便没有使用extends直接继承某个类,它也继承Object
 *
 *    抽象类的子类可以有两种情况：
 *      1.普通类，普通类继承抽象类，必须实现所有的抽象方法。
 *      2.抽象类，抽象子类不需要实现抽象方法，抽象子类可以自由选择实现（或实现或不实现）。
 *
 * 注：抽象类还可以继承一个普通类，但这很罕见，知道即可。
 *
 *
 * @since 11:08
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // Student s = new Student();
        // s.test();
        AbstractPerson.testStatic();
        System.out.println(AbstractPerson.c);
        Student.testStatic();
        System.out.println(Student.c);

        System.out.println("---------------");
        Student s = new Student(100, 200);
        System.out.println(s.a);
        System.out.println(s.getB());


    }
}

// 抽象的人类
abstract class AbstractPerson  {
    int a;
    private int b = 10;

    public int getB() {
        return b;
    }

    static int c = 20;
    {

    }
    static {}

    public void test() {
        System.out.println("我是抽象人类中的test实现方法");
    }

    public static void testStatic() {
        System.out.println("我是抽象人类中的static静态实现方法");
    }

    // 定义抽象方法
    public abstract void testAbstract();

    public abstract void testAbstract2();

    // 定义构造器
    public AbstractPerson(int a, int b) {
        // super();
        this.a = a;
        this.b = b;
    }

    public AbstractPerson() {
        // super();
    }
}

/*
    在实现抽象方法时,建议直接alt+回车,报错的类名
    这是最快的方式
 */
class Student extends AbstractPerson {
    @Override
    public void testAbstract() {
    }

    @Override
    public void testAbstract2() {
    }

    public Student(int a, int b) {
        super(a, b);
    }

    public Student() {
        // super();
    }
}

abstract class AbstractTeacher extends AbstractPerson {

}